package com.zt.bus.alipay.controller;

import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.zt.bus.alipay.util.AlipayUtil;
import com.zt.bus.alipay.util.PayUtil;
import com.zt.bus.alipay.util.SignUtils;
import com.zt.bus.constant.BusConstant;
import com.zt.bus.order.model.OrderPayment;
import com.zt.bus.order.service.OrderPaymentService;
import com.zt.servlet.Response;
import com.zt.util.DateUtil;
import com.zt.util.StringUtil;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayConstants;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 创建时间：2016年11月2日 下午4:16:32
 * 
 * @author andy
 * @version 2.2
 */
@Controller
@RequestMapping("/alipay")
public class PayController {

    private static final Logger LOG = Logger.getLogger(PayController.class);

    @Autowired
    private OrderPaymentService orderPaymentService;

    /**
     * 支付下订单
     * 
     * @param request
     * @param response
     *            支付金额
     */
    @RequestMapping(value = "/pay", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject orderPay(HttpServletRequest request, HttpServletResponse response) {
        LOG.info("支付宝支付开始");
        String orderId = request.getParameter("orderId");
        String phone = request.getParameter("phone");

        if (StringUtil.isEmpty(orderId) || StringUtil.isEmpty(phone)) {
            Response.responseError("订单号或手机号码为空!");
        }
        Double cashnum = 0.02;
        Map<String, String> param = new HashMap<>();
        // 公共请求参数
        param.put("app_id", AlipayUtil.ALIPAY_APPID);// 商户订单号
        param.put("method", "alipay.trade.app.pay");// 交易金额
        param.put("format", AlipayConstants.FORMAT_JSON);
        param.put("charset", AlipayConstants.CHARSET_UTF8);
        param.put("timestamp", DateUtil.formatDateTime(new Date()));
        param.put("version", "1.0");
        param.put("notify_url", "http://investor.lingducapital.com/custom-bus/alipay/pay/notify.do"); // 支付宝服务器主动通知商户服务
        param.put("sign_type", AlipayConstants.SIGN_TYPE_RSA);

        // 得到订单信息
        OrderPayment orderPayment = orderPaymentService.getOrderPayment(BusConstant.PayPlatform.ALIPAY_APP, orderId,
                phone);

        Map<String, Object> pcont = new HashMap<>();
        // 支付业务请求参数
        pcont.put("out_trade_no", orderPayment.getTradeNo()); // 商户订单号
        pcont.put("total_amount", String.valueOf(cashnum));// 交易金额
        pcont.put("subject", "定制公交订单号:" + orderId); // 订单标题
        pcont.put("body", "定制公交");// 对交易或商品的描述
        pcont.put("product_code", "QUICK_MSECURITY_PAY");// 销售产品码

        param.put("biz_content", JSONObject.fromObject(pcont).toString()); // 业务请求参数
                                                                           // 不需要对json字符串转义
        Map<String, String> payMap = new HashMap<>();
        try {
            param.put("sign", PayUtil.getSign(param, AlipayUtil.APP_PRIVATE_KEY)); // 业务请求参数
            payMap.put("params", PayUtil.getSignEncodeUrl(param, true));
            payMap.put("out_trade_no", orderPayment.getTradeNo());
            // 成功，插入订单信息
            orderPaymentService.createOrderPayment(orderPayment);

        } catch (Exception e) {
			LOG.info("调起支付失败:" + e.getMessage());
            e.printStackTrace();
        }

		LOG.info("返回参数:" + payMap);
        LOG.info("支付宝支付结束");
        return Response.response(JSONObject.fromObject(payMap));
    }

    /**
     * 
     * @param request
     * @param response
     * @param tradeno
     *            支付宝订单交易编号
     * @param orderno
     *            商家交易编号
     * @param callback
     */
    @RequestMapping(value = "/pay/query", method = RequestMethod.POST)
    public void orderPayQuery(HttpServletRequest request, HttpServletResponse response, String tradeno, String orderno,
            String callback) {
        LOG.info("[/alipay/pay/query]");
        if (StringUtil.isEmpty(tradeno) && StringUtil.isEmpty(orderno)) {
            // WebUtil.response(response, WebUtil.packJsonp(callback, JSON
            // .toJSONString(new JsonResult(-1, "订单号不能为空", new ResponseData()),
            // SerializerFeatureUtil.FEATURES)));
        }

        AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest(); // 统一收单线下交易查询
        // 只需要传入业务参数
        Map<String, Object> param = new HashMap<>();
        param.put("out_trade_no", orderno); // 商户订单号
        param.put("trade_no", tradeno);// 交易金额
        alipayRequest.setBizContent(JSONObject.fromObject(param).toString()); // 不需要对json字符串转义

        Map<String, String> restmap = new HashMap<String, String>();// 返回提交支付宝订单交易查询信息
        boolean flag = false; // 查询状态
        try {
            AlipayTradeQueryResponse alipayResponse = AlipayUtil.getAlipayClient().execute(alipayRequest);
            if (alipayResponse.isSuccess()) {
                // 调用成功，则处理业务逻辑
                if ("10000".equals(alipayResponse.getCode())) {
                    // 订单创建成功
                    flag = true;
                    restmap.put("order_no", alipayResponse.getOutTradeNo());
                    restmap.put("trade_no", alipayResponse.getTradeNo());
                    restmap.put("buyer_logon_id", alipayResponse.getBuyerLogonId());
                    restmap.put("trade_status", alipayResponse.getTradeStatus());
                    LOG.info("订单查询结果：" + alipayResponse.getTradeStatus());
                } else {
                    LOG.info("订单查询失败：" + alipayResponse.getMsg() + ":" + alipayResponse.getSubMsg());
                }
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        if (flag) {
            // 订单查询成功
            // WebUtil.response(response,
            // WebUtil.packJsonp(callback,
            // JSON.toJSONString(new JsonResult(1, "订单查询成功", new
            // ResponseData(null, restmap)),
            // SerializerFeatureUtil.FEATURES)));
        } else { // 订单查询失败
        // WebUtil.response(response, WebUtil.packJsonp(callback, JSON
        // .toJSONString(new JsonResult(-1, "订单查询失败", new ResponseData()),
        // SerializerFeatureUtil.FEATURES)));
        }
    }

    /**
     * 订单支付微信服务器异步通知
     * 
     * @param request
     * @param response
     */
    @RequestMapping(value = "/pay/notify", method = RequestMethod.POST)
    @ResponseBody
    public String orderPayNotify(HttpServletRequest request, HttpServletResponse response) {
        LOG.info("支付宝开始回调");
        // 获取到返回的所有参数 先判断是否交易成功trade_status 再做签名校验
        // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
        // 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
        // 3、校验通知中的seller_id（或者seller_email)
        // 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
        // 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
        if ("TRADE_SUCCESS".equals(request.getParameter("trade_status"))) {
            Enumeration<?> pNames = request.getParameterNames();
            Map<String, String> param = new HashMap<String, String>();
            try {
                while (pNames.hasMoreElements()) {
                    String pName = (String) pNames.nextElement();
                    param.put(pName, request.getParameter(pName));
                }

                // 商户订单号
                String out_trade_no = param.get("out_trade_no");
                // 支付宝交易号
                String trade_no = param.get("trade_no");
                boolean signVerified = AlipaySignature.rsaCheckV1(param, AlipayUtil.ALIPAY_PUBLIC_KEY,
                        AlipayConstants.CHARSET_UTF8);
                if (signVerified) {
                    // 验签成功后 处理订单信息
                    // 按照支付结果异步通知中的描述，对支付结果中的业务内容进行1\2\3\4二次校验，校验成功后在response中返回success，校验失败返回failure
                    orderPaymentService.paymentSetResult(out_trade_no, trade_no, true, "订单支付通知： 支付成功，订单号"
                            + out_trade_no);
                    LOG.info("订单支付成功：" + JSONObject.fromObject(param));
                    return "SUCCESS";
                } else {
                    // TODO 验签失败则记录异常日志，并在response中返回failure.
                    orderPaymentService.paymentSetResult(out_trade_no, trade_no, false, "订单支付失败，订单号" + out_trade_no);
                    LOG.info("订单支付失败：" + JSONObject.fromObject(param));
                    return "FAILED";
                }
            } catch (Exception e) {
                LOG.info(e.getMessage());
                LOG.info("订单支付失败：" + JSONObject.fromObject(param));
                e.printStackTrace();
            }
        }
        LOG.info("支付宝回调结束");
        return "SUCCESS";
    }

    /**
     * 订单退款
     * 
     * @param request
     * @param response
     */
    @RequestMapping(value = "/pay/refund", method = RequestMethod.POST)
    public void orderPayRefund(HttpServletRequest request, HttpServletResponse response) {
        LOG.info("[/alipay/pay/refund]");
        // tradeno 支付宝交易订单号
        // orderno 商家交易订单号
        String orderno = "TNO2017060914473726500000001";
        if (StringUtil.isEmpty(orderno)) {
            // WebUtil.response(response, WebUtil.packJsonp(callback,
            // JSONObject.fromObject(new JsonResult(-1, "订单号不能为空", new
            // ResponseData()), SerializerFeatureUtil.FEATURES)));
        }

        AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest(); // 统一收单交易退款接口
        // 只需要传入业务参数
        Map<String, Object> param = new HashMap<>();
        param.put("out_trade_no", orderno); // 商户订单号
        // param.put("trade_no", tradeno);// 支付宝订单号
        param.put("refund_amount", 0.01);// 退款金额
        param.put("refund_reason", "测试支付退款");// 退款金额
        param.put("out_request_no", PayUtil.getRefundNo()); // 退款单号
        alipayRequest.setBizContent(JSONObject.fromObject(param).toString()); // 不需要对json字符串转义

        Map<String, Object> restmap = new HashMap<>();// 返回支付宝退款信息
        boolean flag = false; // 查询状态
        try {
            AlipayTradeRefundResponse alipayResponse = AlipayUtil.getAlipayClient().execute(alipayRequest);
            if (alipayResponse.isSuccess()) {
                // 调用成功，则处理业务逻辑
                if ("10000".equals(alipayResponse.getCode())) {
                    // 订单创建成功
                    flag = true;
                    restmap.put("out_trade_no", alipayResponse.getOutTradeNo());
                    restmap.put("trade_no", alipayResponse.getTradeNo());
                    restmap.put("buyer_logon_id", alipayResponse.getBuyerLogonId());// 用户的登录id
                    restmap.put("gmt_refund_pay", alipayResponse.getGmtRefundPay()); // 退看支付时间
                    restmap.put("buyer_user_id", alipayResponse.getBuyerUserId());// 买家在支付宝的用户id
                    LOG.info("订单退款结果：退款成功");
                    LOG.info(JSONObject.fromObject(restmap));
                } else {
                    LOG.info("订单查询失败：" + alipayResponse.getMsg() + ":" + alipayResponse.getSubMsg());
                }
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        if (flag) {
            // 订单查询成功
            // WebUtil.response(response,
            // WebUtil.packJsonp(callback,
            // JSON.toJSONString(new JsonResult(1, "订单退款成功", new
            // ResponseData(null, restmap)),
            // SerializerFeatureUtil.FEATURES)));
        } else { // 订单查询失败
        // WebUtil.response(response, WebUtil.packJsonp(callback, JSON
        // .toJSONString(new JsonResult(-1, "订单退款失败", new ResponseData()),
        // SerializerFeatureUtil.FEATURES)));
        }
    }

    /**
     * 
     * @param request
     * @param response
     */
    @RequestMapping(value = "/pay/refund/query", method = RequestMethod.POST)
    public void orderPayRefundQuery(HttpServletRequest request, HttpServletResponse response) {
        LOG.info("[/alipay/pay/refund/query]");

        String orderno = "TNO2017060914473726500000001";
        // orderno 商家订单号
        // tradeno 支付宝订单号
        if (StringUtil.isEmpty(orderno)) {
            // WebUtil.response(response,
            // WebUtil.packJsonp(callback,
            // JSON.toJSONString(new JsonResult(-1, "商家订单号或支付宝订单号不能为空", new
            // ResponseData()),
            // SerializerFeatureUtil.FEATURES)));
        }

        AlipayTradeFastpayRefundQueryRequest alipayRequest = new AlipayTradeFastpayRefundQueryRequest(); // 统一收单交易退款查询
        // 只需要传入业务参数
        Map<String, Object> param = new HashMap<>();
        param.put("out_trade_no", orderno); // 商户订单号
        // param.put("trade_no", tradeno);// 支付宝订单号
        param.put("out_request_no", orderno);// 请求退款接口时，传入的退款请求号，如果在退款请求时未传入，则该值为创建交易时的外部交易号
        alipayRequest.setBizContent(JSONObject.fromObject(param).toString()); // 不需要对json字符串转义

        Map<String, Object> restmap = new HashMap<>();// 返回支付宝退款信息
        boolean flag = false; // 查询状态
        try {
            AlipayTradeFastpayRefundQueryResponse alipayResponse = AlipayUtil.getAlipayClient().execute(alipayRequest);
            if (alipayResponse.isSuccess()) {
                // 调用成功，则处理业务逻辑
                if ("10000".equals(alipayResponse.getCode())) {
                    // 订单创建成功
                    flag = true;
                    restmap.put("out_trade_no", alipayResponse.getOutTradeNo());
                    restmap.put("trade_no", alipayResponse.getTradeNo());
                    restmap.put("out_request_no", alipayResponse.getOutRequestNo());// 退款订单号
                    restmap.put("refund_reason", alipayResponse.getRefundReason()); // 退款原因
                    restmap.put("total_amount", alipayResponse.getTotalAmount());// 订单交易金额
                    restmap.put("refund_amount", alipayResponse.getTotalAmount());// 订单退款金额
                    LOG.info("订单退款查询结果：退款成功");
                    LOG.info(JSONObject.fromObject(restmap));
                } else {
                    LOG.info("订单失败：" + alipayResponse.getMsg() + ":" + alipayResponse.getSubMsg());
                }
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        if (flag) {
            // 订单查询成功
            // WebUtil.response(response,
            // WebUtil.packJsonp(callback,
            // JSON.toJSONString(new JsonResult(1, "订单退款成功", new
            // ResponseData(null, restmap)),
            // SerializerFeatureUtil.FEATURES)));
        } else { // 订单查询失败
        // WebUtil.response(response, WebUtil.packJsonp(callback, JSON
        // .toJSONString(new JsonResult(-1, "订单退款失败", new ResponseData()),
        // SerializerFeatureUtil.FEATURES)));
        }
    }

}
